package com.miner.updatedemo.service;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import com.miner.MainActivity;
import com.miner.UpdateActivity;
import com.miner.updatedemo.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import static com.miner.MainActivity.START_DOWNLOAD_EXTRA;
import static com.miner.MainActivity.UPDATE_URL_EXTRA;

public class DownloadAPKService extends Service {

    private String LOG_TAG = DownloadAPKService.class.getName();
    public static final String DOWNLOAD_THREAD_NAME = "Download_Thread";
    private UpdateProgressListener mListener;
    private Activity mActivity;
    private long mTotalSize;
    private File mApkFile;
    private NotificationManager mNotifyManager;
    private Notification.Builder mBuilder;
    private boolean mIsStart;

    public DownloadAPKService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(LOG_TAG, "onStartCommand");
        String url = intent.getStringExtra(MainActivity.UPDATE_URL_EXTRA);

        Intent notifyIntent = new Intent(this, UpdateActivity.class);
        notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        notifyIntent.putExtra(UPDATE_URL_EXTRA, url);
        notifyIntent.putExtra(START_DOWNLOAD_EXTRA, true);
        PendingIntent notifyPendingIntent =
                PendingIntent.getActivity(
                        this,
                        0,
                        notifyIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );

        mNotifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mBuilder = new Notification.Builder(this);
        mBuilder.setContentTitle("Update Download")
                .setContentText("下载更新中")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(notifyPendingIntent);

        mIsStart = true;
        DownloadRunnable mRunnable = new DownloadRunnable(url);
        new Thread(mRunnable, DOWNLOAD_THREAD_NAME).start();

        startForeground(ID, mBuilder.build());
        return super.onStartCommand(intent, flags, startId);
    }

    private class DownloadRunnable implements Runnable {
        private final String url;

        DownloadRunnable(String url) {
            this.url = url;
        }

        @Override
        public void run() {
            if (mIsStart) {
                download(url);
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new DownloadBinder();
    }

    public class DownloadBinder extends Binder {
        public DownloadAPKService getService() {
            return DownloadAPKService.this;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(LOG_TAG, "onDestroy");
        unregisterListener();
        stopForeground(true);
    }

    private static final int UPDATE_WAITING = 0;
    private static final int UPDATE_PROGRESS = 1;
    private static final int DOWNLOAD_COMPLETE = 2;
    private static final int DOWNLOAD_Failed = 3;

    private static final int ID = 12570;
    public static final String PROGRESS_VALUE_EXTRA = "progress_value";
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Intent intent;
            switch (msg.what) {
                case UPDATE_WAITING:
                    mBuilder.setContentText("waiting...")
                            .setProgress(0, 0, false);
                    mNotifyManager.notify(ID, mBuilder.build());
                    sendBroadcast(new Intent().setAction(UpdateActivity.UPDATE_WAITING_ACTION));
                    break;
                case UPDATE_PROGRESS:
                    double result = (((long) msg.obj) / (double) mTotalSize) * 100;
                    if (mListener != null)
                        mListener.onProgress((float) result);
                    mBuilder.setProgress(100, (int) result, false)
                            .setContentText((int) result + "%");
                    mNotifyManager.notify(ID, mBuilder.build());
                    intent = new Intent(UpdateActivity.UPDATE_PROGRESS_ACTION);
                    intent.putExtra(PROGRESS_VALUE_EXTRA, result);
                    sendBroadcast(intent);
                    break;
                case DOWNLOAD_COMPLETE:
                    if (mListener != null) {
                        mListener.onComplete();
                    }
                    mBuilder.setContentText("Download complete")
                            .setProgress(0, 0, false);
                    mNotifyManager.notify(ID, mBuilder.build());
                    mNotifyManager.cancel(ID);
                    if (mActivity != null && !mActivity.isFinishing())
                        mActivity.finish();
                    stopForeground(true);
                    installApk(getApplicationContext(), Uri.fromFile(mApkFile));
                    sendBroadcast(new Intent().setAction(UpdateActivity.UPDATE_COMPLETE_ACTION));
                    mIsStart = false;
                    break;
                case DOWNLOAD_Failed:
                    if (mListener != null) {
                        mListener.onFailed();
                    }
                    mBuilder.setContentText("Download failed")
                            .setProgress(0, 0, false);
                    mNotifyManager.notify(ID, mBuilder.build());
                    mNotifyManager.cancel(ID);
                    if (mActivity != null && !mActivity.isFinishing())
                        mActivity.finish();
                    stopForeground(true);
                    sendBroadcast(new Intent().setAction(UpdateActivity.UPDATE_FAILED_ACTION));
                    mIsStart = false;
                    break;
            }
        }
    };

    private void download(String url) {
        InputStream is = null;
        FileOutputStream fos = null;
        mHandler.sendMessage(mHandler.obtainMessage(UPDATE_WAITING));
        try {
            String filename = url.substring(url.lastIndexOf("/") + 1);
            URL myURL = new URL(url);
            URLConnection conn = myURL.openConnection();
            conn.connect();
            is = conn.getInputStream();
            mTotalSize = conn.getContentLength();
            if (this.mTotalSize <= 0) throw new RuntimeException("无法获知文件大小 ");
            if (is == null) throw new RuntimeException("无法获取链接输入流");
            mApkFile = new File("/sdcard/" + filename);
            fos = new FileOutputStream(mApkFile);
            byte buf[] = new byte[2048];
            int len;
            long currentSize = 1;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
                currentSize += len;
                fos.flush();
                mHandler.sendMessageDelayed(mHandler.obtainMessage(UPDATE_PROGRESS, currentSize), 0 * 1000);
            }
            mHandler.sendMessage(mHandler.obtainMessage(DOWNLOAD_COMPLETE));
        } catch (Exception e) {
            e.printStackTrace();
            mHandler.sendMessage(mHandler.obtainMessage(DOWNLOAD_Failed));
        } finally {
            Log.e(LOG_TAG, "finally block");
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void registerListener(UpdateProgressListener listener) {
        this.mListener = listener;
    }

    public void unregisterListener() {
        this.mListener = null;
    }

    public interface UpdateProgressListener {
        void onProgress(float f);

        void onComplete();

        void onFailed();
    }

    public void installApk(Context context, Uri apkPath) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.setDataAndType(apkPath, "application/vnd.android.package-archive");
        context.startActivity(intent);
    }

    public void setBindActivity(Activity activity) {
        this.mActivity = activity;
    }
}
